HDU 5639 Deletion(最大流)
题意:
$N,M\le 2\times 10^3,N个点M条边的无向图$
$每次选择从图中删掉一些边,要求选出来的边构成的子图的每个连通块最多只有一个环$
$问最少需要删几次才能把所有边都删掉$
分析:
$这想法真是炫酷,虽然我做过混合图欧拉回路那个题,早都忘了$
$第二种解法也是炫酷$
代码:
//
// Created by TaoSama on 2016-04-07
// Copyright (c) 2016 TaoSama. All rights reserved.
//
#pragma comment(linker, "/STACK:102400000,102400000")
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>
using namespace std;
#define pr(x) cout << #x << " = " << x << " "
#define prln(x) cout << #x << " = " << x << endl
const int N = 4e3 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7;
const int M = 8e3 + 10;
struct Edge {
int v, nxt, cap;
} edge[M << 1];
int head[N], cnt;
void addDouble(int u, int v, int c1, int c2 = 0) {
edge[cnt] = {v, head[u], c1};
head[u] = cnt++;
edge[cnt] = {u, head[v], c2};
head[v] = cnt++;
}
int lev[N], cur[N];
bool bfs(int s, int t) {
queue<int> q;
memset(lev, 0, sizeof lev);
q.push(s); lev[s] = 1;
while(q.size() && !lev[t]) {
int u = q.front(); q.pop();
for(int i = head[u]; ~i; i = edge[i].nxt) {
int v = edge[i].v;
if(edge[i].cap > 0 && !lev[v]) {
lev[v] = lev[u] + 1;
q.push(v);
}
}
}
return lev[t];
}
int dfs(int u, int t, int delta) {
if(u == t || !delta) return delta;
int ret = 0;
for(int i = cur[u]; ~i; i = edge[i].nxt) {
int v = edge[i].v;
if(edge[i].cap > 0 && lev[v] == lev[u] + 1) {
int d = dfs(v, t, min(delta, edge[i].cap));
cur[u] = i;
ret += d; delta -= d;
edge[i].cap -= d;
edge[i ^ 1].cap += d;
if(delta == 0) return ret;
}
}
lev[u] = 0;
return ret;
}
int dinic(int s, int t) {
int ret = 0;
while(bfs(s, t)) {
for(int i = s; i <= t; ++i) cur[i] = head[i];
ret += dfs(s, t, INF);
}
return ret;
}
int n, m;
int u[M], v[M];
bool check(int x) {
cnt = 0; memset(head, -1, sizeof head);
int s = 0, t = n + m + 1;
for(int i = 1; i <= n; ++i) addDouble(s, i, x);
for(int i = 1; i <= m; ++i) {
addDouble(u[i], i + n, 1);
addDouble(v[i], i + n, 1);
addDouble(i + n, t, 1);
}
return dinic(s, t) == m;
}
int main() {
#ifdef LOCAL
freopen("C:\\Users\\TaoSama\\Desktop\\in.txt", "r", stdin);
// freopen("C:\\Users\\TaoSama\\Desktop\\out.txt","w",stdout);
#endif
ios_base::sync_with_stdio(0);
int t; scanf("%d", &t);
while(t--) {
scanf("%d%d", &n, &m);
for(int i = 1; i <= m; ++i)
scanf("%d%d", u + i, v + i);
int l = 0, r = m;
while(l <= r) {
int m = l + r >> 1;
if(check(m)) r = m - 1;
else l = m + 1;
}
printf("%d\n", l);
}
return 0;
}